/*
 * Created by JFormDesigner on Fri Jun 19 14:00:24 CST 2020
 */

package com.kancy.slimmaker.ui;

import com.kancy.slimmaker.core.JarSlimMaker;
import com.kancy.slimmaker.log.Log;
import com.kancy.slimmaker.log.LogLevel;
import com.kancy.slimmaker.ui.comp.ConsolePrintStream;
import com.kancy.slimmaker.ui.comp.SimpleFileDirectoryChooser;
import com.kancy.slimmaker.utils.AlertUtils;
import com.kancy.slimmaker.utils.PopupMenuUtils;
import net.miginfocom.swing.MigLayout;
import org.apache.commons.io.FileUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author kancy
 */
public class Main extends JFrame implements ActionListener {

    private static AtomicBoolean process = new AtomicBoolean(false);
    private static AtomicBoolean run = new AtomicBoolean(false);

    private JProgressBar progressBar = new JProgressBar();

    public Main() {
        initComponents();
        setIconImage(new ImageIcon(getClass().getResource("/icon.png")).getImage());
        panel2.add(progressBar, BorderLayout.SOUTH);
        initConsole();
        addPopupMenu();
        addDropTarget();
    }

    private void addDropTarget() {
        DropTargetAdapter dropTargetAdapter = new DropTargetAdapter() {
            @Override
            public void drop(DropTargetDropEvent dtde) {
                try {
                    // 接收拖拽来的数据
                    dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                    List<File> list = (List<File>) (dtde.getTransferable().getTransferData(DataFlavor.javaFileListFlavor));
                    for (File file : list) {
                        if (file.getAbsolutePath().toLowerCase().endsWith(".jar")) {
                            textField_jar_file_path.setText(file.getAbsolutePath());
                            break;
                        }
                    }
                    // 指示拖拽操作已完成
                    dtde.dropComplete(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        // 添加拖拽
        new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE,dropTargetAdapter);
        new DropTarget(textArea_package, DnDConstants.ACTION_COPY_OR_MOVE,dropTargetAdapter);
        new DropTarget(textField_jar_file_path, DnDConstants.ACTION_COPY_OR_MOVE,dropTargetAdapter);
        new DropTarget(textArea_console, DnDConstants.ACTION_COPY_OR_MOVE,dropTargetAdapter);
    }


    /**
     * Invoked when an action occurs.
     *
     * @param e
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        String actionCommand = e.getActionCommand();
        if (Objects.equals(actionCommand, "console_clear")){
            textArea_console.setText(null);
            return;
        }
        if (Objects.equals(actionCommand, "log_level")){
            String logLevel = AlertUtils.getUserChooseInput(this, new String[]{
                    "DEBUG", "INFO", "WARN", "ERROR"
            }, "请选择日志级别");
            try {
                Log.setLogLevel(LogLevel.valueOf(logLevel.toUpperCase()));
            } catch (Exception ex) {
                AlertUtils.msg(this, "设置失败：{}", logLevel);
            }
            return;
        }
    }

    private void addPopupMenu() {
        JPopupMenu jPopupMenu = new JPopupMenu();
        PopupMenuUtils.addMenuItem(jPopupMenu, "清空", this, "console_clear");
        PopupMenuUtils.addMenuItem(jPopupMenu, "日志级别", this, "log_level");
        PopupMenuUtils.addPopupMenu(textArea_console, jPopupMenu);
    }

    private void initConsole() {
        ConsolePrintStream console = new ConsolePrintStream(System.out, textArea_console);
        System.setOut(console);
        System.setErr(console);
    }

    private void button_select_jarActionPerformed(ActionEvent e) {
        SimpleFileDirectoryChooser chooser = new SimpleFileDirectoryChooser();
        chooser.setOnlyFileSelection()
                .setFileNameExtensionFilter("*.jar", new String[]{"jar"})
                .setMultiSelectionEnabled(false)
                .setTitle("请选择需要简化的jar包文件");
        chooser.showOpenDialog();

        if (chooser.hasSelectedFile()){
            String selectedFilePath = chooser.getSelectedFilePath();
            textField_jar_file_path.setText(selectedFilePath);
        }
    }

    private void button_slimActionPerformed(ActionEvent e) {

        if (!process.compareAndSet(false, true)){
            AlertUtils.msg(this, "已经有任务在处理，请稍等！");
            return;
        }

        new Thread(() -> {
            try {
                progressBar.setIndeterminate(true);

                String jarFilePath = textField_jar_file_path.getText();
                if (Objects.isNull(jarFilePath) || jarFilePath.isEmpty()){
                    AlertUtils.msg("请选择需要简化的JAR文件！");
                    return;
                }

                String packageStr = textArea_package.getText();
                List<String> packages = new ArrayList(textArea_package.getLineCount());
                if (Objects.nonNull(packageStr) && !packageStr.isEmpty()){
                    packageStr = packageStr.replace("\r\n","\n");
                    String[] lines = packageStr.split("\n");
                    for (String line : lines) {
                        if (Objects.nonNull(line) && !line.isEmpty()){
                            packages.add(line.trim());
                        }
                    }
                }

                try {
                    JarSlimMaker jarSlimMaker = null;
                    if (!packages.isEmpty()){
                        jarSlimMaker = new JarSlimMaker(new File(jarFilePath), packages);
                    }else {
                        jarSlimMaker = new JarSlimMaker(new File(jarFilePath));
                    }

                    jarSlimMaker.setExcludePackage(checkBox_isExcludePackage.isSelected());
                    jarSlimMaker.setDeleteClassLoaderLog(checkBox_delete_cl_log.isSelected());
                    jarSlimMaker.setOverwriteClassLoaderLog(checkBox_overwrite_log.isSelected());

                    jarSlimMaker.slim();
                } catch (Exception ex) {
                    AlertUtils.msg("处理失败：{}", ex.getMessage());
                }
            } finally {
                process.set(false);
                progressBar.setIndeterminate(false);
            }
        }).start();

    }

    private void button_runActionPerformed(ActionEvent e) {
        String jarFilePath = textField_jar_file_path.getText();
        if (Objects.isNull(jarFilePath) || jarFilePath.isEmpty()){
            AlertUtils.msg("请选择需要简化的JAR文件！");
            return;
        }

        File file = FileUtils.getFile(jarFilePath);
        File slimFile = FileUtils.getFile(file.getParent(), file.getName()
                .replace(".jar","-slim.jar")
                .replace(".JAR","-slim.jar"));
        if (!(slimFile.exists() && slimFile.isFile())){
            AlertUtils.msg("请先完成简化！");
            return;
        }


        if (!run.compareAndSet(false, true)){
            AlertUtils.msg(this, "已经有运行的程序，请稍等！");
            return;
        }

        new Thread(() -> {
            try {
                ProcessBuilder processBuilder = new ProcessBuilder("java","-jar", slimFile.getAbsolutePath());
                processBuilder.directory(file.getParentFile());
                processBuilder.redirectOutput(FileUtils.getFile(FileUtils.getTempDirectory(), "slim.log"));
                Process process = processBuilder.start();
                process.waitFor();
            } catch (Exception ex) {
                Log.error(ex.getMessage(), ex);
                AlertUtils.msg("操作失败！");
            }finally {
                run.set(false);
            }
        }).start();

    }


    private void initComponents() {
        // JFormDesigner - Component initialization - DO NOT MODIFY  //GEN-BEGIN:initComponents
        splitPane1 = new JSplitPane();
        panel1 = new JPanel();
        label_select_jar = new JLabel();
        textField_jar_file_path = new JTextField();
        button_select_jar = new JButton();
        label_package_name = new JLabel();
        scrollPane_list = new JScrollPane();
        textArea_package = new JTextArea();
        button_slim = new JButton();
        button_run = new JButton();
        checkBox_overwrite_log = new JCheckBox();
        checkBox_delete_cl_log = new JCheckBox();
        checkBox_isExcludePackage = new JCheckBox();
        panel2 = new JPanel();
        scrollPane2 = new JScrollPane();
        textArea_console = new JTextArea();

        //======== this ========
        setMinimumSize(new Dimension(450, 500));
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("JAR\u6587\u4ef6\u7cbe\u7b80\u5668");
        Container contentPane = getContentPane();
        contentPane.setLayout(new BorderLayout());

        //======== splitPane1 ========
        {
            splitPane1.setOrientation(JSplitPane.VERTICAL_SPLIT);

            //======== panel1 ========
            {
                panel1.setLayout(new MigLayout(
                    "hidemode 3",
                    // columns
                    "[fill]" +
                    "[400,fill]" +
                    "[fill]",
                    // rows
                    "[]" +
                    "[]" +
                    "[]" +
                    "[]" +
                    "[]" +
                    "[]" +
                    "[]"));
                panel1.add(label_select_jar, "cell 0 1");
                panel1.add(textField_jar_file_path, "cell 1 1,growx");

                //---- button_select_jar ----
                button_select_jar.addActionListener(e -> button_select_jarActionPerformed(e));
                panel1.add(button_select_jar, "cell 2 1");
                panel1.add(label_package_name, "cell 0 2 1 4,align right top,grow 0 0");

                //======== scrollPane_list ========
                {

                    //---- textArea_package ----
                    textArea_package.setRows(5);
                    textArea_package.setToolTipText("<html>\n1.\u6307\u5b9a\u54ea\u4e9b\u5305\u9700\u8981\u88ab\u7b80\u5316\uff0c\u591a\u4e2a\u5305\u6362\u884c\u5206\u5272\u3002<br>\n2.\u5982\u679c\u4e0d\u6307\u5b9a\uff0c\u9ed8\u8ba4\u7b80\u5316\u6240\u6709\u5305\u4e0b\u7684class\u6587\u4ef6\u3002<br>\n3.\u52fe\u9009\u6392\u9664\u5305\u540d\uff0c\u8fd9\u91cc\u7684\u5305\u540d\u7c7b\u5c31\u4e0d\u4f1a\u88ab\u7cbe\u7b80\uff0c\u5176\u4f59\u7684\u7c7b\u4f1a\u88ab\u7cbe\u7b80\u3002<br><br>\n</html>");
                    scrollPane_list.setViewportView(textArea_package);
                }
                panel1.add(scrollPane_list, "cell 1 2 1 5,dock center");

                //---- button_slim ----
                button_slim.addActionListener(e -> button_slimActionPerformed(e));
                panel1.add(button_slim, "cell 2 2,aligny top,growy 0");

                //---- button_run ----
                button_run.addActionListener(e -> button_runActionPerformed(e));
                panel1.add(button_run, "cell 2 3,aligny top,growy 0");

                //---- checkBox_overwrite_log ----
                checkBox_overwrite_log.setToolTipText("\u662f\u5426\u91cd\u65b0\u8986\u76d6\u7c7b\u52a0\u8f7d\u7684\u65e5\u5fd7");
                checkBox_overwrite_log.setSelected(true);
                panel1.add(checkBox_overwrite_log, "cell 2 4,aligny top,growy 0");

                //---- checkBox_delete_cl_log ----
                checkBox_delete_cl_log.setSelected(true);
                panel1.add(checkBox_delete_cl_log, "cell 2 5,aligny top,growy 0");

                //---- checkBox_isExcludePackage ----
                checkBox_isExcludePackage.setSelected(true);
                checkBox_isExcludePackage.setToolTipText("\u4e0d\u7b80\u5316\u6307\u5b9a\u7684\u5305\u540d\u7684\u7c7b");
                panel1.add(checkBox_isExcludePackage, "cell 2 6,aligny top,growy 0");
            }
            splitPane1.setTopComponent(panel1);

            //======== panel2 ========
            {
                panel2.setLayout(new BorderLayout());

                //======== scrollPane2 ========
                {
                    scrollPane2.setViewportView(textArea_console);
                }
                panel2.add(scrollPane2, BorderLayout.CENTER);
            }
            splitPane1.setBottomComponent(panel2);
        }
        contentPane.add(splitPane1, BorderLayout.CENTER);

        initComponentsI18n();

        pack();
        setLocationRelativeTo(getOwner());
        // JFormDesigner - End of component initialization  //GEN-END:initComponents
    }

    private void initComponentsI18n() {
        // JFormDesigner - Component i18n initialization - DO NOT MODIFY  //GEN-BEGIN:initI18n
        ResourceBundle bundle = ResourceBundle.getBundle("i18n");
        label_select_jar.setText(bundle.getString("JarSlimMaker.label_select_jar.text"));
        button_select_jar.setText(bundle.getString("JarSlimMaker.button_select_jar.text"));
        label_package_name.setText(bundle.getString("JarSlimMaker.label_package_name.text"));
        button_slim.setText(bundle.getString("JarSlimMaker.button_slim.text"));
        button_run.setText(bundle.getString("JarSlimMaker.button_run.text"));
        checkBox_overwrite_log.setText(bundle.getString("JarSlimMaker.checkBox_overwrite_log.text"));
        checkBox_delete_cl_log.setText(bundle.getString("JarSlimMaker.checkBox_delete_cl_log.text"));
        checkBox_delete_cl_log.setToolTipText(bundle.getString("JarSlimMaker.checkBox_delete_cl_log.toolTipText"));
        checkBox_isExcludePackage.setText(bundle.getString("JarSlimMaker.checkBox_isExcludePackage.text"));
        // JFormDesigner - End of component i18n initialization  //GEN-END:initI18n
    }

    // JFormDesigner - Variables declaration - DO NOT MODIFY  //GEN-BEGIN:variables
    private JSplitPane splitPane1;
    private JPanel panel1;
    private JLabel label_select_jar;
    private JTextField textField_jar_file_path;
    private JButton button_select_jar;
    private JLabel label_package_name;
    private JScrollPane scrollPane_list;
    private JTextArea textArea_package;
    private JButton button_slim;
    private JButton button_run;
    private JCheckBox checkBox_overwrite_log;
    private JCheckBox checkBox_delete_cl_log;
    private JCheckBox checkBox_isExcludePackage;
    private JPanel panel2;
    private JScrollPane scrollPane2;
    private JTextArea textArea_console;
    // JFormDesigner - End of variables declaration  //GEN-END:variables
}
